home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_11_12 / splash / splash.cpp < prev    next >
Text File  |  1993-01-14  |  17KB  |  645 lines

  1. /*
  2.  * Version 1.8
  3.  * Written by Jim Morris,  jegm@sgi.com
  4.  * Kudos to Larry Wall for inventing SP
  5.  * Copyrights only exist on the regex stuff,  and all
  6.  * have been left intact.
  7.  * The only thing I ask is that you let me know of any nifty fixes or
  8.  * additions.
  9.  * Credits:
  10.  * I'd like to thank Michael Golan <mg@Princeton.EDU> for his critiques
  11.  * and clever suggestions. Some of which have actually been implemented
  12.  */
  13. #include <iostream.h>
  14. #include <string.h>
  15. #include <malloc.h>
  16. #include <stdio.h>
  17.  
  18. #ifdef    __TURBOC__
  19. #pragma hdrstop
  20. #endif
  21.  
  22. #include "splash.h"
  23.  
  24. //************************************************************
  25. // VarString Implementation
  26. //************************************************************
  27.  
  28. VarString& VarString::operator=(const char *s)
  29. {
  30.     int nl= strlen(s);
  31.     if(nl+1 >= allocated) grow((nl-allocated)+allocinc);
  32.     assert(allocated > nl+1);
  33.     strcpy(a, s);
  34.     len= nl;
  35.     return *this;
  36. }
  37.  
  38. VarString& VarString::operator=(const VarString& n)
  39. {
  40.     if(this != &n){
  41.     if(n.len+1 >= allocated){ // if it is not big enough
  42. #        ifdef    DEBUG
  43.         fprintf(stderr, "~operator=(VarString&) a= %p\n", a);
  44. #        endif
  45.         delete [] a; // get rid of old one
  46.         allocated= n.allocated;
  47.         allocinc= n.allocinc;
  48.         a= new char[allocated];
  49. #        ifdef    DEBUG
  50.         fprintf(stderr, "operator=(VarString&) a= %p, source= %p\n", a, n.a);
  51. #        endif
  52.     }
  53.         len= n.len;
  54.     strcpy(a, n.a);
  55.     }
  56.     return *this;
  57. }
  58.  
  59. void VarString::grow(int n)
  60. {
  61.     if(n == 0) n= allocinc;
  62.     allocated += n;
  63.     char *tmp= new char[allocated];
  64.     strcpy(tmp, a);
  65. #ifdef    DEBUG
  66.     fprintf(stderr, "VarString::grow() a= %p, old= %p, allocinc= %d\n", tmp, a, allocinc);
  67.     fprintf(stderr, "~VarString::grow() a= %p\n", a);
  68. #endif
  69.     delete [] a;
  70.     a= tmp;
  71. }
  72.  
  73. void VarString::add(char c)
  74. {
  75.     if(len+1 >= allocated) grow();
  76.     assert(allocated > len+1);
  77.     a[len++]= c; a[len]= '\0';
  78. }
  79.  
  80. void VarString::add(const char *s)
  81. {
  82.     int nl= strlen(s);
  83.     if(len+nl >= allocated) grow(((len+nl)-allocated)+allocinc);
  84.     assert(allocated > len+nl);
  85.     strcat(a, s);
  86.     len+=nl;
  87. }
  88.  
  89. void VarString::add(int ip, const char *s)
  90. {
  91.     int nl= strlen(s);
  92.     if(len+nl >= allocated) grow(((len+nl)-allocated)+allocinc);
  93.     assert(allocated > len+nl);
  94.     memmove(&a[ip+nl], &a[ip], (len-ip)+1); // shuffle up
  95.     memcpy(&a[ip], s, nl);
  96.     len+=nl;
  97.     assert(a[len] == '\0');
  98. }
  99.  
  100. void VarString::remove(int ip, int n)
  101. {
  102.     assert(ip+n <= len);
  103.     memmove(&a[ip], &a[ip+n], len-ip); // shuffle down
  104.     len-=n;
  105.     assert(a[len] == '\0');    
  106. }
  107.  
  108. //************************************************************
  109. // SPString stuff
  110. //************************************************************
  111.  
  112. // assignments
  113. SPString& SPString::operator=(const SPString& n)
  114. {
  115.     if(this == &n) return *this;
  116.     pstr= n.pstr;
  117.     return *this;
  118. }
  119.  
  120. SPString& SPString::operator=(const substring& sb)
  121. {
  122.     VarString tmp(sb.pt, sb.len);
  123.     pstr= tmp;
  124.     return *this;
  125. }
  126.  
  127. // concatenations
  128. SPString SPString::operator+(const SPString& s) const
  129. {
  130.     SPString ts(*this);
  131.     ts.pstr.add(s);    
  132.     return ts; 
  133. }
  134.  
  135. SPString SPString::operator+(const char *s) const
  136. {
  137.     SPString ts(*this);
  138.     ts.pstr.add(s);
  139.     return ts; 
  140. }
  141.  
  142. SPString SPString::operator+(char c) const
  143. {
  144.     SPString ts(*this);
  145.     ts.pstr.add(c);
  146.     return ts; 
  147. }
  148.  
  149. SPString operator+(const char *s1, const SPString& s2)
  150. {
  151.     SPString ts(s1);
  152.     ts = ts + s2;
  153. //    cout << "s2[0] = " << s2[0] << endl; // gives incorrect error
  154.     return ts; 
  155. }
  156.  
  157. //************************************************************
  158. // other stuff
  159. //************************************************************
  160.  
  161. char SPString::chop(void)
  162. {
  163.     int n= length();
  164.     if(n <= 0) return '\0'; // empty
  165.     char tmp= pstr[n-1];
  166.     pstr.remove(n-1);
  167.     return tmp;
  168. }
  169.  
  170. int SPString::index(const SPString& s, int offset)
  171. {
  172.     if(offset < 0) offset= 0;
  173.     for(int i=offset;i<length();i++){
  174.     if(strncmp(&pstr[i], s, s.length()) == 0) return i;
  175.     }
  176.  
  177.     return -1;
  178. }
  179.  
  180. int SPString::rindex(const SPString& s, int offset)
  181. {
  182.     if(offset == -1) offset= length()-s.length();
  183.     else offset= offset-s.length()+1;
  184.     if(offset > length()-s.length()) offset= length()-s.length();
  185.       
  186.     for(int i=offset;i>=0;i--){
  187.     if(strncmp(&pstr[i], s, s.length()) == 0) return i;
  188.     }
  189.     return -1;
  190. }
  191.  
  192. SPString::substring SPString::substr(int offset, int len)
  193. {
  194.     if(len == -1) len= length() - offset; // default use rest of string
  195.     if(offset < 0){
  196.     offset= length() + offset;  // count from end of string
  197.     if(offset < 0) offset= 0;   // went too far, adjust to start
  198.     }
  199.     return substring(*this, offset, len);
  200. }
  201.  
  202. // this is private
  203. // it shrinks or expands string as required
  204. void SPString::insert(int pos, int len, const char *s, int nlen)
  205. {
  206.     if(pos < length()){ // nothing to delete if not true
  207.     if((len+pos) > length()) len= length() - pos;
  208.     pstr.remove(pos, len);  // first remove subrange
  209.     }else pos= length();
  210.  
  211.     VarString tmp(s, nlen);
  212.     pstr.add(pos, tmp);        // then insert new substring
  213. }
  214.  
  215. int SPString::m(Regexp& r)
  216. {
  217.     return r.match(*this);
  218. }
  219.  
  220. int SPString::m(const char *pat, const char *opts)
  221. {
  222. int iflg= strchr(opts, 'i') != NULL;
  223.     Regexp r(pat, iflg?Regexp::nocase:0);
  224.     return m(r);
  225. }
  226.  
  227. int SPString::m(Regexp& r, SPStringList& psl)
  228. {
  229.     if(!r.match(*this)) return 0;
  230.     psl.reset();    // clear it first
  231.     Range rng;
  232.     for (int i=0; i<r.groups(); i++){
  233.         rng= r.getgroup(i);
  234.     psl.push(substr(rng.start(), rng.length()));
  235.     }
  236.     return r.groups();
  237. }
  238.  
  239. int SPString::m(const char *pat, SPStringList& psl, const char *opts)
  240. {
  241. int iflg= strchr(opts, 'i') != NULL;
  242.     Regexp r(pat, iflg?Regexp::nocase:0);
  243.     return m(r, psl);
  244. }
  245.  
  246. //
  247. // I know! This is not fast, but it works!!
  248. //
  249. int SPString::tr(const char *sl, const char *rl, const char *opts)
  250. {
  251.     if(length() == 0 || strlen(sl) == 0) return 0;
  252.  
  253.     int cflg= strchr(opts, 'c') != NULL; // thanks Michael
  254.     int dflg= strchr(opts, 'd') != NULL;
  255.     int sflg= strchr(opts, 's') != NULL;
  256.  
  257.     int cnt= 0, flen= 0;
  258.     SPString t;
  259.     unsigned char lstc= '\0', fr[256];
  260.     
  261.     // build search array, which is a 256 byte array that stores the index+1
  262.     // in the search string for each character found, == 0 if not in search
  263.     memset(fr, 0, 256);
  264.     for(int i=0;i<strlen(sl);i++){
  265.     if(i && sl[i] == '-'){ // got a range
  266.         assert(i+1 < strlen(sl) && lstc <= sl[i+1]); // sanity check
  267.         for(unsigned char c=lstc+1;c<=sl[i+1];c++){
  268.         fr[c]= ++flen;
  269.         }
  270.         i++; lstc= '\0';
  271.     }else{
  272.         lstc= sl[i];
  273.         fr[sl[i]]= ++flen;
  274.     }
  275.     }
  276.  
  277.     int rlen;
  278.     // build replacement list
  279.     if((rlen=strlen(rl)) != 0){
  280.     for(i=0;i<rlen;i++){
  281.         if(i && rl[i] == '-'){ // got a range
  282.         assert(i+1 < rlen && t[t.length()-1] <= rl[i+1]); // sanity check
  283.         for(char c=t[i-1]+1;c<=rl[i+1];c++) t += c;
  284.         i++;
  285.         }else t += rl[i];
  286.     }
  287.     }
  288.  
  289.     // replacement string that is shorter uses last character for rest of string
  290.     // unless the delete option is in effect or it is empty
  291.     while(!dflg && rlen && flen > t.length()){
  292.     t += t[t.length()-1]; // duplicate last character
  293.     }
  294.  
  295.     rlen= t.length(); // length of translation string   
  296.    
  297.     // do translation, and deletion if dflg (actually falls out of length of t)
  298.     // also squeeze translated characters if sflg
  299.  
  300.     SPString tmp; // need this in case dflg, and string changes size
  301.     for(i=0;i<length();i++){
  302.     int off;
  303.     if(cflg){ // complement, ie if NOT in f
  304.         char rc= !dflg ? t[t.length()-1] : '\0'; // always use last character for replacement
  305.         if((off=fr[(*this)[i]]) == 0){ // not in map
  306.         cnt++;
  307.         if(!dflg && (!sflg || tmp.length() == 0 || tmp[tmp.length()-1] != rc))
  308.             tmp += rc;
  309.         }else tmp += (*this)[i]; // just stays the same
  310.     }else{ // in fr so substitute with t, if no equiv in t then delete
  311.         if((off=fr[(*this)[i]]) > 0){
  312.         off--; cnt++;
  313.